/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-03-18     desktop       the first version
 */
#include <all_code.h>

/*  导入log工具 */
#define DBG_TAG "uart_device.c"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

/* 串 口 设 备 句 柄 */
rt_device_t ble_uart_device;

/* 中断接收信号量 */
static struct rt_semaphore ble_rx_semaphore;
static struct rt_semaphore rx_data_finish_semaphore;

rt_uint8_t temp_buff[LINE_LEN];            //主机用于接收数据的BUFF
/*  0:手部定时值，1:手部角度 ，2:手部开关值，3:手心开关值，4:脚部定时值，5:脚部速度值，6:脚部开关值    */
rt_uint8_t temp_data[7];

static rt_thread_t data_receive_tid = RT_NULL;
static rt_thread_t data_analysis_tid = RT_NULL;

/*函数名：  data_receive_semaphore_process
    作者：    Jingle_lan
    日期：    2022-03-16
    功能：   串口接收回调函数，相当于中断服务函数，*/
static rt_err_t data_receive_semaphore_process(rt_device_t dev, rt_size_t size)
{
    /* 串 口 接 收 到 数 据 后 产 生 中 断， 调 用 此 回 调 函 数， 然 后 发 送 接 收 信 号 量 */
    rt_sem_release(&ble_rx_semaphore);
    return RT_EOK;
}

/*函数名：  data_receive_entry
    作者：    Jingle_lan
    日期：    2022-03-16
    功能：   串口数据校验接收线程，*/
static void data_receive_entry(void *param)
{
    static rt_uint8_t uart_num = 0;
    while(1)
    {

        /* 在这里阻塞线程来等待信号量，完成下面的数据解析  */
        rt_sem_take(&ble_rx_semaphore, RT_WAITING_FOREVER);

        /* 接收一个字节数据，把它放在temp_buff 这个变量里，然后校验数据  */
        rt_device_read(ble_uart_device, 0, &temp_buff[uart_num++] , 1);

        if(1 == uart_num)
        {
            /*  校验头字节   */
            if(0Xb0 != temp_buff[0])
            {
                uart_num = 0;
            }
        }

        /*  校验尾字节   */
        if(LINE_LEN == uart_num)
        {
            if(0xbb == temp_buff[LINE_LEN - 1])
            {
                /*  一帧数据接收完成，释放信号量，等待解析  */
                rt_sem_release(&rx_data_finish_semaphore);
            }

            uart_num = 0;
        }

    }

}



/*函数名：  hex_process
    作者：    Jingle_lan
    日期：    2022-03-16
    功能：   hex数据解析函数，*/
static rt_uint8_t hex_process(rt_int16_t value)
{
    return (value / 16) * 10 + (value % 16);
}


/*函数名：  data_analisy
    作者：    Jingle_lan
    日期：    2022-03-16
    功能：   数据解析函数，这里参考通信协议去解析*/
static void data_analisy(void)
{
    /*  手部信息处理  */
    if(temp_buff[1] == 0xb1)
    {
        if(temp_buff[2] == 0xb2)
        {
            temp_data[0] = hex_process(temp_buff[3]);
        }

        if(temp_buff[4] == 0xb3)
        {
            temp_data[1] = hex_process(temp_buff[5]);
        }


        if(temp_buff[6] == 0xb4)
        {
            temp_data[2] = hex_process(temp_buff[7]);

            //释放一个手部调度信号量
            rt_sem_release(&hand_sch_semaphore);

        }
    }


    /*  手心信息处理  */
    if(temp_buff[8] == 0xb5)
    {
        if(temp_buff[9] == 0xb6)
        {
            temp_data[3] = hex_process(temp_buff[10]);
            //释放一个手心调度信号量
            rt_sem_release(&palm_sch_semaphore);
        }
    }

    /*  脚部信息处理  */
    if(temp_buff[11] == 0xb7)
    {
        if(temp_buff[12] == 0xb8)
        {
            temp_data[4] = hex_process(temp_buff[13]);
        }

        if(temp_buff[14] == 0xb9)
        {
            temp_data[5] = hex_process(temp_buff[15]);
        }

        if(temp_buff[16] == 0xba)
        {
            temp_data[6] = hex_process(temp_buff[17]);

            /*  如果开关是打开的，就释放一个信号量，如果开关是关着的，就释放另一个信号量*/
            /*  要注意上电时候默认要释放停止的信号量  */
            /*  由于电机是正转倒转 互相来的，所以需要正转线程和反转线程  */

            //释放一个脚部调度信号量
            rt_sem_release(&foot_sch_semaphore);
        }


    }
}

/*函数名：  data__analysis_entry
    作者：    Jingle_lan
    日期：    2022-03-16
    功能：   串口数据解析线程，*/
static void data_analysis_entry(void *param)
{
    while(1)
    {
        /*  获取一个信号量来解析数据    */
        rt_sem_take(&rx_data_finish_semaphore, RT_WAITING_FOREVER);

        /*  解析手部数据  */
        data_analisy();

        /*  在这里释放一个信号量，去检测 三个设备状态。*/
        /*  可以将三个设备的开关 状态分别做6个线程来切换。*/
        /*  每个设备都是 状态更新一次就会挂起线程 */
    }

}

/*函数名：  ble_uart_init
    作者：    Jingle_lan
    日期：    2022-03-16
    功能：   串口设备及线程初始化函数，*/
void uart_device_init(void)
{
    rt_err_t uart_log;
    /* 配 置 串口参 数 */
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;

    /* 初 始 化 信 号 量 */
    rt_sem_init(&ble_rx_semaphore, "ble_rx_semaphore", 0, RT_IPC_FLAG_PRIO);
    rt_sem_init(&rx_data_finish_semaphore, "rx_data_finish_semaphore", 0, RT_IPC_FLAG_PRIO);

    /* 查 找 串 口 设 备 */
    ble_uart_device = rt_device_find(BLE_UART_NAME);
    if( ble_uart_device != RT_NULL)
    {
        LOG_I("find %s device is successed\t\n",BLE_UART_NAME);
    }
    else{
        LOG_E("find %s device is failed\t\n",BLE_UART_NAME);
    }

    /*  设置串口为中断接收模式 */
    uart_log = rt_device_open(ble_uart_device, RT_DEVICE_FLAG_INT_RX);
    if( uart_log == RT_EOK)
    {
        LOG_I("open %s device is successed\t\n",BLE_UART_NAME);
    }
    else{
        LOG_E("open %s device is failed\t\n",BLE_UART_NAME);
    }


    /* 配置串口默认参数 波特率115200 ， 8位数据位 1位停止位 */
    uart_log = rt_device_control(ble_uart_device, RT_DEVICE_CTRL_CONFIG, &config);
    if( uart_log == RT_EOK)
    {
        LOG_I("control %s device is successed\t\n",BLE_UART_NAME);
    }
    else{
        LOG_E("control %s device is failed\t\n",BLE_UART_NAME);
    }

    /* 配置串口接收 服务函数 ,在这个函数里通过释放信号量，进入  协议处理线程来处理信号量 */
    uart_log = rt_device_set_rx_indicate(ble_uart_device, data_receive_semaphore_process);
    if( uart_log == RT_EOK)
    {
        LOG_I("add %s device receiver interrupt function is successed\t\n",BLE_UART_NAME);
    }
    else{
        LOG_E("add %s device receiver interrupt function is failed\t\n",BLE_UART_NAME);
    }

    /*  初始化线程并接收线程句柄，如果线程创建成功就启动线程  */
    data_receive_tid = rt_thread_create("receive", data_receive_entry, RT_NULL, 1024, 10, 10);
    if(data_receive_tid != RT_NULL)
    {
        rt_thread_startup(data_receive_tid);
    }
    data_analysis_tid = rt_thread_create("analysis", data_analysis_entry, RT_NULL, 1024, 11, 10);
    if(data_analysis_tid != RT_NULL)
    {
        rt_thread_startup(data_analysis_tid);
    }
}
